import os
from io import BytesIO

import numpy as np
from PIL import Image
from flask import Blueprint, Response, request, json
from threading import Lock
from service.service_ocr import baidu_predict, check_cpu_usage
from utils.uitils_logger import Mylogger

logger = Mylogger("controller_ocr.log").get_logger()

ocr = Blueprint('ocr',__name__)

'''计数器'''
lock = Lock()
# controller_ocr.py 顶部
ocr_execution_lock = Lock()  # 新增：保护 OCR 执行

apiCount = 0

cpuErrorCount = 0

ocrErrorCount = 0

@ocr.route('/get_error_count', methods=["GET"])
def get_error_count():
    return Response(json.dumps({"apiCount": apiCount, "cpuErrorCount": cpuErrorCount, "ocrErrorCount": ocrErrorCount}, ensure_ascii=False), content_type="application/json")

@ocr.route('/image-ocr', methods=["POST"])
def image_ocr():
    json_str = request.data
    json_str = json_str.decode()  # python3.6及以上不用这一句代码
    dict_data = json.loads(json_str)
    imageUrl = dict_data.get("imageUrl")

    if imageUrl is None:
        logger.error(f"❌ 参数错误! 【{imageUrl}】")
        result = {"message": 'error', "code": 1, "data": f"❌ 参数错误! 【{imageUrl}】"}
        return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

    if not os.path.exists(imageUrl):
        logger.error(f"❌ 图片不存在! 【{imageUrl}】")
        result = {"message": 'error', "code": 1, "data": f"❌ 图片不存在! 【{imageUrl}】"}
        return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

    # 初始化 result
    result = {"message": 'error', "code": 1, "data": ""}

    global cpuErrorCount,ocrErrorCount

    with lock:
        global apiCount
        apiCount += 1
        current_count = apiCount  # 记录当前请求的计数，用于日志

    try:
        # 在锁外执行耗时操作（如检查 CPU、调用 OCR），避免长时间持有锁
        if current_count > 1:
            if check_cpu_usage():
                cpuErrorCount += 1
                result["data"] = f"❌ CPU 使用率过高! 【{imageUrl}】CPU 连续异常次数【{cpuErrorCount}】"
                return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

        # 执行 OCR 识别（耗时操作）
        with ocr_execution_lock:  # ✅ 保护 OCR 调用
            ocr_result = baidu_predict(imageUrl)
            ocrErrorCount = 0
            cpuErrorCount = 0
            # 构造成功响应
            result = {"message": 'success', "code": 0, "data": ocr_result}

    except Exception as e:
        ocrErrorCount += 1
        logger.error(f"❌ ocr识图 连续异常次数【{ocrErrorCount}】 识别异常: {e}", exc_info=True)
        result["data"] = f"❌ 识别异常 【{e}】【{imageUrl}】 ocr识图 连续异常次数【{ocrErrorCount}】"
    finally:
        # ✅ 无论成功或失败，都要在 finally 中将计数器 -1，保证资源释放
        with lock:
            apiCount -= 1
            logger.info(f"✅ 请求处理完成，当前并发数: {apiCount}")

    return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

@ocr.route('/image-ocr-stream', methods=["POST"])
def image_ocr_stream():
    # 判断是否有文件上传 multipart/form-data
    if 'file' not in request.files:
        logger.error("❌ 未上传文件")
        result = {"message": 'error', "code": 1, "data": "❌ 未上传文件"}
        return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

    file = request.files['file']

    # 检查文件名是否为空
    if file.filename == '':
        logger.error("❌ 空文件名")
        result = {"message": 'error', "code": 1, "data": "❌ 空文件名"}
        return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

    # 初始化 result
    result = {"message": 'error', "code": 1, "data": ""}

    global cpuErrorCount, ocrErrorCount

    with lock:
        global apiCount
        apiCount += 1
        current_count = apiCount  # 记录当前请求的计数，用于日志
        # logger.info(f"✅ 请求进入，当前并发数: {current_count}")

    try:
        # 在锁外执行耗时操作（如检查 CPU、调用 OCR），避免长时间持有锁
        if current_count > 1:
            if check_cpu_usage():
                cpuErrorCount += 1
                result = {"message": 'error', "code": 1, "data": f"❌ cpu使用率过高! 【{file.filename}】CPU 连续异常次数【{cpuErrorCount}】"}
                return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")

        # 执行 OCR 识别（耗时操作）
        with ocr_execution_lock:  # ✅ 保护 OCR 调用
            # 读取文件流
            file_stream = BytesIO(file.read())
            image = Image.open(file_stream).convert('RGB')  # 使用 PIL 读取图像

            # 将 PIL 图像转换为 numpy 数组（BGR 格式，适配 paddleocr）
            image_np = np.array(image)[:, :, ::-1].copy()  # RGB -> BGR

            # 使用 paddleocr 识别
            ocr_result = baidu_predict(image_np)

            ocrErrorCount = 0
            cpuErrorCount = 0
            result = {"message": 'success', "code": 0, "data": ocr_result}

    except Exception as e:
        ocrErrorCount += 1
        logger.error(f"❌ ocr识图 连续异常次数【{ocrErrorCount}】 识别异常: {e}", exc_info=True)
        result["data"] = f"❌ 识别异常 【{e}】【{file.filename}】ocr识图 连续异常次数【{ocrErrorCount}】"
    finally:
        # ✅ 无论成功或失败，都要在 finally 中将计数器 -1，保证资源释放
        with lock:
            apiCount -= 1
            logger.info(f"✅ 请求处理完成，当前并发数: {apiCount}")

    return Response(json.dumps(result, ensure_ascii=False), content_type="application/json")